package com.stsmobile;


import java.util.ArrayList;

import com.stsmobile.R;
import com.stsmobile.dataclass.Shipment;
import com.stsmobile.dataclass.Specimen;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.TextView;
import android.widget.Toast;

public class LogSpecimenData extends Activity{
	protected static final String NON_NUMBER_INPUT = "The user input value was not a number. Please retry.";
	protected static final String INVALID_INPUT = "The input value was negative or would make intact+damaged"+
	" greater than total specimens.";
	protected static final String ERROR_MESSAGE = "Log was not successful. Please try again."; 
	protected static final String SUCCESS_MESSAGE = "Log was successful."; 
	protected static final String NOT_SENT_MESSAGE = "Data entered was discarded- shipment reception has " +
	"not been logged."; 
	private String[] specimenTitles;
	private String[][] specimenData;
	private String[][] dataTitles;
	Shipment shipment;
	ArrayList<Specimen> specimenList;
	private Context context;
	private BaseExpandableListAdapter listAdapter;

	@Override
	public void onResume(){
		super.onResume();
		if(STSApplication.loggingOut()){
			finish();
		}
		if(STSApplication.toHome()){
			finish();
		}
	}

	@Override
	public void onCreate(Bundle a){
		//Necessary android stuff
		super.onCreate(a);
		setContentView(R.layout.logspecimendata);
		context = this;

		//Get the current shipment's data, returning if there is none.
		shipment = STSApplication.getShipment();
		specimenList = shipment.getSpecimenList();
		if(shipment==null){
			//TODO: tell the user that they don't have a shipment and put them back to Welcome page
		}

		//Populate the header data
		findAndSetText(R.id.shipmentID, " "+shipment.getShipment_id());
		findAndSetText(R.id.shippedOnText, " "+shipment.getShipDate());
		findAndSetText(R.id.shipStatusText, " "+shipment.getShipStatus());
		findAndSetText(R.id.receivedOnText, " "+shipment.getReceiveDate());
		findAndSetText(R.id.institutionText, " "+shipment.getInstitution());
		findAndSetText(R.id.labText, " "+shipment.getLab());

		//Populate the ExpandableListView data
		populateSpecimenTitles();
		populateSpecimenData();

		//Create the expanding specimen list
		ExpandableListView listView = (ExpandableListView) this.findViewById(R.id.expandableListView1);
		listAdapter = new CustomListAdapter(this,specimenTitles,specimenData);
		listView.setAdapter(listAdapter);
		listView.setOnChildClickListener(new OnChildClickListener() {
			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				if(childPosition == 2 || childPosition == 3){
					editSpecimenPopup(groupPosition, childPosition);
				}
				return false;
			}
		});


		Button logChanges = (Button) findViewById(R.id.b_log);
		logChanges.setOnClickListener(new View.OnClickListener() 
		{
			@Override
			public void onClick(View v) 
			{
				for(int i=0;i<specimenTitles.length;i++){
					int spec_id=Integer.parseInt(specimenTitles[i]);
					int intact=Integer.parseInt(specimenData[i][2]);
					int damaged=Integer.parseInt(specimenData[i][3]);
					int missing=Integer.parseInt(specimenData[i][4]);

					STSApplication.setSpecimen(spec_id, intact, damaged, missing);
				}
				String result = STSApplication.updateShipment();
				
				makeXmlMessageToast(result, Toast.LENGTH_LONG);
				if(!result.contains("<error>")) finish();
			}
		});

		Button enter = (Button) findViewById(R.id.b_discard);
		enter.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				makeXmlMessageToast("<msg>"+NOT_SENT_MESSAGE+"</msg>",
						Toast.LENGTH_LONG);
				finish();
			}
		});
	}

	/**
	 * A popup that allows users to edit 
	 * @param groupPosition
	 * @param childPosition
	 */

	private void editSpecimenPopup(final int groupPosition,final int childPosition)
	{
		//Defines the look of the popup
		AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
		final EditText integerBox = new EditText(context); 
		integerBox.setHint("Insert Quantity here");
		dialogBuilder.setTitle("Modify " + dataTitles[groupPosition][childPosition]);
		dialogBuilder.setMessage("ENTER VALUE");
		dialogBuilder.setView(integerBox);

		//Defines the behavior of the popup
		dialogBuilder.setPositiveButton("Change", new DialogInterface.OnClickListener() 
		{
			@Override
			public void onClick(DialogInterface dialog, int which) {
				try
				{
					//convert newValue to an integer to check integrity
					Editable newValueEditable = integerBox.getEditableText();
					int newVal = Integer.parseInt(newValueEditable.toString());
					//gets the index of the value that is _not_ being edited
					int otherIndex = 2; if(childPosition==2) otherIndex++;
					int otherVal = Integer.parseInt(specimenData[groupPosition][otherIndex]);
					int countVal = Integer.parseInt(specimenData[groupPosition][1]);
					//FIXME: VERY HIGH POSSIBILITY OF CONVERSION BUGS. Please fix me.

					if(newVal+otherVal<=countVal && newVal>=0){
						//Then the data is valid-->
						//Calculate the new "missing" value
						int missing = countVal-newVal-otherVal;
						//Save newVal and Missing to specimen data array
						specimenData[groupPosition][childPosition]=Integer.toString(newVal);
						specimenData[groupPosition][4]=Integer.toString(missing);
					}else{
						//The data is either negative or lies outside the count
						makeXmlMessageToast("<msg>"+INVALID_INPUT+"</msg>",
								Toast.LENGTH_LONG);

					}
				}catch (NumberFormatException e)
				{
					//error parsing, user input something that was not an integer.
					makeXmlMessageToast("<msg>"+NON_NUMBER_INPUT+"</msg>",
							Toast.LENGTH_LONG);
				}

				//refresh view
				listAdapter.notifyDataSetChanged();
			}
		});
		dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
		{
			@Override
			public void onClick(DialogInterface dialog, int which) {
				//Just exit the dialog with no changes
			}
		});
		AlertDialog alertdiagle = dialogBuilder.create();
		alertdiagle.show();
	}


	/**
	 * Initially populates the view's specimen data.
	 * @param id
	 * @param s
	 */
	private void populateSpecimenData()
	{
		specimenData = new String[specimenList.size()][5];
		dataTitles = new String[specimenList.size()][5];
		for (int i = 0; i < specimenList.size(); i++)
		{
			dataTitles[i][0] = specimenList.get(i).getSpecimenTitle()+": ";
			specimenData[i][0] = "" + specimenList.get(i).getSpecimenDescription();
			dataTitles[i][1] = "Specimen Count: ";
			specimenData[i][1] = "" + specimenList.get(i).getQuantity();
			dataTitles[i][2] = "Intact: ";
			specimenData[i][2] = "" + specimenList.get(i).getIntact();
			dataTitles[i][3] = "Damaged: ";
			specimenData[i][3] = "" + specimenList.get(i).getDamaged();
			dataTitles[i][4] = "Missing: ";
			specimenData[i][4] = "" + specimenList.get(i).getMissing();
		}
	}

	/**
	 * initially populates the view's specimen titles
	 * @param id
	 * @param s
	 */
	private void populateSpecimenTitles(){
		specimenTitles = new String[specimenList.size()];
		for (int i = 0; i < specimenList.size(); i++){
			specimenTitles[i] = Integer.toString(specimenList.get(i).getSpecimenID());
		}
	}


	private void findAndSetText(int id, String s){
		TextView txt = (TextView) findViewById(id);
		txt.setText(s);
	}


	/**
	 * Custom Adapter for the list to use. Gets the data from the shipment
	 * and places it in the list
	 * 
	 * @author Charlie Hatcher
	 */
	public class CustomListAdapter extends BaseExpandableListAdapter{
		private Context context;
		private String[] groups;
		private String[][] children;

		public CustomListAdapter(Context context, String[] groups, String[][] children){
			this.context = context;
			this.groups=groups;
			this.children=children;
		}

		@Override
		public boolean areAllItemsEnabled()
		{
			return true;
		}

		@Override
		public Object getChild(int groupPosition, int childPosition) {
			return dataTitles[groupPosition][childPosition]+"\t"+children[groupPosition][childPosition];
		}

		@Override
		public long getChildId(int groupPosition, int childPosition) {
			return children[groupPosition].length;
		}

		@Override
		public View getChildView(int groupPosition, int childPosition,
				boolean isLastChild, View convertView, ViewGroup parent) 
		{
			String child = (String) getChild(groupPosition, childPosition);

			if (convertView == null) {
				LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				convertView = infalInflater.inflate(R.layout.child_row, null);
			}

			TextView childtxt = (TextView) convertView.findViewById(R.id.childname1);

			childtxt.setText(child);

			return convertView;
		}

		@Override
		public int getChildrenCount(int groupPosition) {
			return children[groupPosition].length;
		}

		@Override
		public Object getGroup(int groupPosition) {
			return groups[groupPosition];
		}

		@Override
		public int getGroupCount() {
			return groups.length;
		}

		@Override
		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		@Override
		public View getGroupView(int groupPosition, boolean isExpanded,
				View convertView, ViewGroup parent) {
			//			String group = (String) getGroup(groupPosition);

			if (convertView == null) {
				LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				convertView = infalInflater.inflate(R.layout.group_row, null);
			}

			//Group is being generated/updated-- set the title.
			TextView grouptxt = (TextView) convertView.findViewById(R.id.groupname);
			grouptxt.setText("Specimen #"+specimenTitles[groupPosition]);

			return convertView;
		}

		@Override
		public boolean hasStableIds() {
			return true;
		}

		@Override
		public boolean isChildSelectable(int groupPosition, int childPosition) {
			if(childPosition == 2 || childPosition == 3){
				return true;
			}
			return false;
		}

	}

	private static final CharSequence ERROR_CONNECTION = "Unable to connect\n" +
	"to the STS database.";
	private static final CharSequence ERROR_NOT_LOGGED_IN = "User is not logged in.";

	private void makeXmlMessageToast(String result, int duration){
		CharSequence message="";

		//Get error message from server's response.
		int startMessage = result.indexOf("<msg>")+5;
		int endMessage = result.indexOf("</msg>");

		if(startMessage!=-1 && endMessage!=-1)
			message = result.substring(startMessage,endMessage);

		if(message.equals(""))
			message=ERROR_CONNECTION;

		if(message.equals("User Authentication Failed: Bad Sitekey"))
			message=ERROR_NOT_LOGGED_IN;

		//Display Error Message to User in a Popup
		Context cur_context = getApplicationContext();
		Toast displaymessage = Toast.makeText(cur_context, message, duration);
		displaymessage.show();
	}

	private static final int MENU_LOGOUT = Menu.FIRST;
	private static final int MENU_HOME = Menu.FIRST + 1;

	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(0,MENU_LOGOUT,0,"Logout");
		menu.add(0,MENU_HOME,0,"Home");
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item){
		switch(item.getItemId()){
		case MENU_LOGOUT:
			logout();
			return true;
		case MENU_HOME:
			home();
			return true;
		}
		return false;
	}

	public void logout(){
		String result = STSApplication.logout();
		makeXmlMessageToast(result, Toast.LENGTH_LONG);
		STSApplication.loggingOut(true);
		finish();
	}

	public void home(){
		STSApplication.toHome(true);
		finish();
	}
}